package WebCore;
use strict;
use warnings;
use Tools::IPCheck;
use utf8;

=head1  NAME

WebCore - 5anet.com Application的主要控制器父类

=head1  SNOPSIS

package ActionClass;
use base qw/WebCore/;
......

=head1  DESCRIPTION

所有的子类均需要继承该父类，在该父类中我们可以做如下的事情
1、use所有需要使用的公用插件和模块类
2、初始化所有的插件
3、hook所有的方法。比如cgiapp_init等等。
4、定义公用的方法

=cut

#定义需要使用的父类
#在开发环境中可以继承CGI::Application
#但是在产品环境中最好改为继承CGI::Application::FastCGI
use base qw/CGI::Application/;
#use base qw/CGI::Application::FastCGI/;


#调试开关
use CGI::Carp qw/fatalsToBrowser warningsToBrowser/;

###################################################
#载入需要使用的插件
###################################################

#自动配置插件
use CGI::Application::Plugin::ConfigAuto qw/cfg/;
#Session插件和cookie
use CGI::Application::Plugin::Session;
use CGI::Cookie;
#url插件
use CGI::Application::Plugin::ActionDispatch;
#日志插件
use CGI::Application::Plugin::LogDispatch;
#缓存插件
#暂时将缓存插件先不配置
use CGI::Application::Plugin::CHI;
#载入数据库插件
use CGI::Application::Plugin::DBH qw/dbh_config dbh/;
#TT2模板插件
use CGI::Application::Plugin::TT;
#表单验证插件
use CGI::Application::Plugin::ValidateRM;
#表单自动填充插件
#use CGI::Application::Plugin::FillInForm;
#动作内进行forward插件
use CGI::Application::Plugin::Forward;

#有助于调试的插件，在生产环境中可以将这些插件
#移去
use CGI::Application::Plugin::ViewCode;
#use CGI::Application::Plugin::DebugScreen;
#use CGI::Application::Plugin::HtmlTidy;

#开始调试
BEGIN {
    $ENV{CGI_APP_DEBUG} = 1;
}

use Data::Dumper;


#初始化CGI::Appliation配置
sub cgiapp_init {
    my $this = shift;

    #日志配置
    $this->log_config(
        LOG_DISPATCH_MODULES=>
        $this->cfg('log_config')
    );

    #Session的配置
    $this->session_config(
        CGI_SESSION_OPTIONS=>[
            $this->cfg('session_driver'),
            $this->query(),
            $this->cfg('session_driver_params')
        ],
        DEFAULT_EXPIRY=>$this->cfg('session_default_expiry'),
        SEND_COOKIE=>0,
    );


    #配置模板系统
    $this->tt_config(
        TEMPLATE_OPTIONS=>$this->cfg('tt2_config'),
    );


    #配置CHI缓存系统
    $this->cache_config(
        $this->cfg('chi_config'),
    );

    #配置数据库系统
    #在以后的情况下还可以直接加入其他的
    #数据库配置，方便在我们使用mysql数据库的时候将
    #数据库的读写分开，比如master, slave
    $this->dbh_config(
        'dbi:'.$this->cfg('db_driver').':host='.
        $this->cfg('db_host').';database='.$this->cfg('db_name'),
        $this->cfg('db_user'),
        $this->cfg('db_pw'),
        $this->cfg('db_attr')
    );


    #默认的表单验证配置
    $this->param('dfv_defaults') ||
        $this->param('dfv_defaults', {
                missing_optional_valid=>1,
                filters=>'trim',
                msgs=>{
                    any_errors=>'err__',
                    prefix=>'err_',
                    invalid=>'格式不正确',
                    missing=>'不能为空',
                    format=>'<span style="color:red;font-weight:bold">'.
                        '<span class="dfv_errors">&nbsp; %s</span></span>',

                }
                ,

            });

    #定义一个通用的数据传输hash数组
    $this->{'tt_var'} = {};
}

#定一个缺省的runmode
sub setup {
    my $this = shift;
    
    $this->mode_param('ac');
    $this->run_modes(
        showcity=>'showcity',
        choicecity=>'choicecity',

    );

}



#定义一些其他的动作
#该动作发生在请求之前
sub cgiapp_prerun {
    my $this = shift;
    $this->{'tt_var'}->{'customer_title'} = $this->get_title;
    #预定义的变量
    $this->{'tt_var'}->{'username'} = $this->session->param('username');
    $this->{'tt_var'}->{'userid'} = $this->session->param('userid');

    #判断是否有选择城市。如果没有选择城市。
    #则显示选择城市的页面
    #取得cookie
#    my %cookie = CGI::Cookie->fetch;
#    my $cityid = undef;
#
#    if ( $cookie{'cityid'} ) {
#        $cityid = $cookie{'cityid'}->value;
#    }
#
#    if ( ! $cityid && $this->get_current_runmode ne 'choicecity' ) {
#        $this->prerun_mode('showcity');
#    }

}



#自定义化的header输出
sub cgiapp_postrun {
    my $this = shift;

    #根据用的IP地址自动选择城市ID
    #现在只关注天气的城市ID
    my %cookies = CGI::Cookie->fetch;
    my $weather_city_id = undef;

    if ( $cookies{'weather_city_id'} ) {
        $weather_city_id = $cookies{'weather_city_id'}->value;
    } else {
        #取得客户端得IP
        my $your_ip = &get_ip();
        my $your_place = &check_ip($your_ip, $this->cfg('ip_db'));
    }


    my $domain = $this->cfg('site_domain');

    my $cookie = CGI::Cookie->new(
        -name=>$this->session->name,
        -value=>$this->session->id,
        -domain=>$domain,
        -expires=>$this->cfg('session_default_expiry'),
        -path=>'/',
    );

    $this->header_type('header'),
    $this->header_props(
        -type=>'text/html',
        -charset=>'UTF-8',
        -cookie=>[$this->get_cookie, $cookie],
        -Pragma=>'no-cache',
    );


}

#定义一个title 
sub get_title {
    return "5anet.com";
}

#定义新的title
sub set_title {
    my $this = shift;
    my $title = shift;
    $this->{'tt_var'}->{'customer_title'} = $title;
}


#定义专门的变量用于存放cookie
sub set_cookie {
    my $this = shift;
    #cookie 对象
    my $cookie = shift;

    $this->{'cookie'} = $cookie;

}

#取得cookie
sub  get_cookie {
    my $this = shift;
    return $this->{'cookie'};
}



#定义一个新的redirect方法，
#原有的插件: CGI::Application::Plugin::Redirect在这里由于我们
#重构了header方法，所以不能使用改插件
#参看该插件代码
sub redirect {
    my $this = shift;
    my $location = shift;
    $this->{'tt_var'}->{'location'} = $location;
    $this->set_title('正在跳转');
    return $this->tt_process('redirect.tt2', $this->{'tt_var'});
}

#定义个用于显示错误信息的方法
#并定义用于跳转的url
sub show_error {
    my $this = shift;
    my $error_msg = shift;
    my $location = shift;
    
    $this->set_title('出错啦 - 5anet.com');
    $this->{'tt_var'}->{'error_msg'} = $error_msg;
    $this->{'tt_var'}->{'location'} = $location;

    return $this->tt_process('show_error.tt2', $this->{'tt_var'});

}


#定义缺省的runMode，用于选择城市
sub showcity {
    my $this = shift;

    $this->set_title('选择您需要查看的城市 - 5anet.com');

    return $this->process_template('showcity.tt2');

}

#定义缺省的runmode, 确定已经选择的城市。
#并将城市变量写入到session
sub choicecity {
    my $this = shift;

    my $cityid = $this->query->param('id');
    if ( !$cityid ) {
        return $this->forward('showcity');
    }

    my $domain = $this->cfg('site_domain');

    #建立一个新的cookie
    my $cookie = new CGI::Cookie(
        -name=>'cityid',
        -value=>$cityid,
        -domain=>$this->cfg('site_domain'),
        -expires=>'+12M',
        -path=>'/',
    );

    $this->set_cookie($cookie);


    return $this->redirect($this->cfg('root_app_url').'home');
}



#定义个缺省的显示模板的函数
sub process_template {
    my $this = shift;
    my $tt_file = shift;

    return $this->tt_process($tt_file, $this->{'tt_var'});
    
}

#定义方法向tt_var中添加变量
sub set_tt_var {
    my $this = shift;
    my $name = shift;
    my $value = shift;

    $this->{'tt_var'}->{$name} = $value;

}

#定义方法从tt_var取得变量
sub get_tt_var {
    my $this = shift;
    my $name = shift;

    return exists $this->{'tt_var'}->{$name} ? 
        $this->{'tt_var'}->{$name}:undef;
}



1;
